home *** CD-ROM | disk | FTP | other *** search
- DEFINT A-Z
- 'REM $INCLUDE Exec.bh
- 'REM $INCLUDE Audio.bc
- 'REM $INCLUDE IFFParse.bh
- 'REM $INCLUDE utility.bc
- 'REM $INCLUDE DOS.bh
- 'REM $INCLUDE graphics.bh
- 'REM $INCLUDE datatypes/Soundclass.bc
- 'REM $INCLUDE datatypes/Pictureclass.bc
- 'REM $INCLUDE asl.bh
-
- REM $INCLUDE Blib/ExecSupport.bas
- REM $INCLUDE BLib/IFFBufIO.bas
-
- CONST ID_CHAN& = &h4248414E
- CONST NTSC_CLOCK& = 3579545&
- CONST PAL_CLOCK& = 3546895&
- CONST AIOCNT = 2
- CONST MAXSAMPLE&= &h20000&
- '
- 'Ask the system if we are PAL or NTSC and set clock constant accordingly
- '
- FUNCTION getAudioClock&
- STATIC GfxBase&, palflag
-
- getAudioClock& = -1&
- palflag = PAL&
- IF PEEKW(LIBRARY("graphics.library") + lib_Version) >= 39 THEN
- 'V39 and above have an early-start independent PAL detection method
-
- palflag = REALLY_PAL&
- END IF
- IF PEEKW(LIBRARY("graphics.library") + DisplayFlags) AND palflag THEN
- getAudioClock& = PAL_CLOCK&
- ELSE
- getAudioClock& = NTSC_CLOCK&
- END IF
- END FUNCTION
- '
- 'Set up the audio I/O block for channel allocation
- '
- SUB allocateAudioChannels(BYVAL audioIO&, BYVAL audioMP&)
- STATIC ioreq&, whichannel&
-
- ioreq& = audioIO& + ioa_Request
-
- POKEL ioreq& + IORequestio_Message + mn_ReplyPort, audioMP& ' the address of a reply port
- POKEB ioreq& + IORequestio_Message + mn_Node + ln_Pri, 0 ' neutral priority
- POKEW ioreq& + IORequestio_Command, ADCMD_ALLOCATE& ' allocate the channels
- POKEB ioreq& + IORequestio_Flags, ADIOF_NOWAIT&
-
- POKEW audioIO& + ioa_AllocKey, 0
-
- whichannel& = &h01020408 ' channel allocation
- POKEL audioIO& + ioa_Data, VARPTR(whichannel&)
- POKEL audioIO& + ioa_Length, 4
- END SUB
-
-
- SUB OpenAudio
- DIM SHARED devopened, port&
- STATIC k
- STATIC device&
- SHARED tclock&
- IF devopened THEN EXIT SUB
-
- tclock&=getAudioClock&
- DIM SHARED aio&(AIOCNT)
-
-
- '
- 'Create a reply port so the audio device can reply to our commands
- '
- port& = CreatePort&(NULL&, 0)
- IF port& THEN
- FOR k=0 TO AIOCNT-1
- aio&(k)=CreateExtIO&(port&,IOAudio_sizeof)
- IF aio&(k)=0 THEN CALL CloseAudio: EXIT SUB
- NEXT k
- allocateAudioChannels aio&(0),port&
- device& = OpenDevice&(SADD("audio.device" + CHR$(0)), 0, aio&(0), 0)
- ' Clone the flags, channel allocation, etc. into other IOAudio requests
- FOR k=1 TO AIOCNT-1
- CopyMem aio&(0),aio&(k),IOaudio_sizeof
- NEXT k
- END IF
- IF device&=0 THEN devopened=-1 ELSE CALL CloseAudio
- END SUB
-
-
- '
- ' Close audio device as opened by OpenAudio, null out pointers
- '
- SUB CloseAudio
- STATIC k
- SHARED devopened,port&
- ' Note - we know we have no outstanding audio requests */
- IF devopened THEN
- CloseDevice aio&(0)
- devopened = 0
- END IF
- FOR k=0 TO AIOCNT-1
- IF aio&(k) THEN
- DeleteExtIO aio&(k)
- aio&(k) = NULL&
- END IF
- NEXT k
- IF port& THEN
- DeletePort port&
- port& = NULL&
- END IF
- END SUB
-
-
- FUNCTION LoadSBody(BYVAL iff&,BYVAL vhdr&)
- SHARED sbytes&
- SHARED sample&
- STATIC memtype&
- STATIC compression
- STATIC cn&
- LoadSBody=0
- cn&=CurrentChunk(iff&)
- IF PEEKL(cn&+cn_type)<>ID_8SVX& OR PEEKL(cn&+cn_ID)<>ID_BODY& THEN
- PRINT "couldn't find BODY chunk"
- EXIT FUNCTION
- END IF
- sbytes& = PEEKL(cn&+cn_Size) - PEEK(cn&+cn_Scan)
- ' if we have to decompress, let's just load it into public mem
- compression= PEEKB(vhdr&+vh_Compression)
- IF compression THEN
- memtype&= MEMF_PUBLIC&
- ELSE
- memtype&= MEMF_CHIP&
- END IF
- sample&=AllocMem(sbytes&,memtype&)
- IF sample&=0 THEN
- PRINT "Not enough memory"
- EXIT FUNCTION
- END IF
- IF ReadChunkBytes(iff&,sample&,sbytes&)<>sbytes& THEN
- PRINT "Can't read whole sample"
- EXIT FUNCTION
- END IF
-
- SELECT CASE compression
- CASE 0
- CASE CMP_FIBDELTA&
- PRINT "Delta compression not yet implemented"
- EXIT FUNCTION
- CASE ELSE
- PRINT "Unknown compression method:";compression
- END SELECT
- LoadSBody=-1
- END FUNCTION
-
- SUB UnloadSBody
- SHARED sample&, sbytes&
- IF sample& THEN
- FreeMem sample&,sbytes&
- sample&=0
- END IF
- sbytes&=0
- END SUB
-
- '
- 'The main play sample routine
- '
- SUB PlaySample(BYVAL vhdr&)
- SHARED aio&(1),tclock&
- SHARED sbytes&,sample&
- STATIC ioreq&,a&,junk&
- STATIC period,volume
- STATIC req ' the index of the Audio Request that is currently playing
- STATIC reqn ' the index of the next request that we are creating
- STATIC sampleptr& ' where we are playing from
- STATIC bytesleft& ' bytes still to play
-
- period= tclock&/PEEKW(vhdr&+vh_samplespersec)
- volume=MAX(PEEKL(vhdr&+vh_volume)*64/&h10000,64)
-
- sampleptr&=sample&
- bytesleft&=sbytes&
-
- a&=aio&(0)
- ioreq&=a&+ioa_Request
-
- POKEW ioreq& + IORequestio_Command , CMD_WRITE&
- POKEB ioreq& + IORequestio_Flags , ADIOF_PERVOL&
- POKEL a& + ioa_Data , sampleptr&
- POKEL a& + ioa_Length , MIN(bytesleft&, MAXSAMPLE&)
- POKEW a& + ioa_Period , period
- POKEW a& + ioa_Volume , volume
- POKEW a& + ioa_Cycles , 1
-
- ' Send the command to start a sound using BeginIO()
- BEGINIO a&
- req=0 ' the first one is now playing
-
- DO
- bytesleft&=bytesleft&-MAXSAMPLE&
- IF bytesleft&<=0 THEN EXIT LOOP
- sampleptr&=sampleptr&+MAXSAMPLE&
-
- reqn = req XOR 1 ' alternate IO Blocks 0 and 1
- a&=aio&(reqn)
- ioreq&=a&+ ioa_Request
-
- POKEW ioreq& + IORequestio_Command , CMD_WRITE&
- POKEB ioreq& + IORequestio_Flags , ADIOF_PERVOL&
- POKEL a& + ioa_Data , sampleptr&
- POKEL a& + ioa_Length , MIN(bytesleft&,MAXSAMPLE&)
- POKEW a& + ioa_Period , period
- POKEW a& + ioa_Volume , volume
- POKEW a& + ioa_Cycles , 1
- BEGINIO a&
-
- junk&= WaitIO(aio&(req)) ' wait for the previous request to finish
-
- req =reqn ' the one we've just started is now playing
-
- LOOP
- ' wait for the final (or only!) io request to finish
- junk&= WaitIO(aio&(req))
-
- PRINT "done!"
- END SUB
-
-
-
- SUB PlayFile (filename$)
- STATIC iff&, stream&, junk&, sp&, vhdr&, camg&, bm&, screenptr&, w, h, depth
- SHARED sbytes&
- iff& = AllocIFF&
- IF iff& THEN
- stream& = xOpen&(SADD(filename$ + CHR$(0)), MODE_OLDFILE&)
- IF stream& THEN
- POKEL iff& + iff_Stream, stream& 'connect the DOS stream
-
- IF PEEKW(LIBRARY("dos.library") + lib_Version) >= 36 THEN
- 'for WB2 and above, use the buffered DOS I/O calls
- junk& = SetVBuf&(stream&, NULL&, BUF_FULL&, 8192)
- initIFFasBufferedDOS iff&
- ELSE
- 'fall back for 1.3 (if you have 1.3 iffparse.library)
- InitIFFasDos iff&
- END IF
-
- IF OpenIFF&(iff&, IFFF_READ&) = 0 THEN
- IF PropChunk&(iff&, ID_8SVX&, ID_VHDR&) = 0 AND _
- StopChunk&(iff&, ID_8SVX&, ID_BODY&) = 0 AND _
- ParseIFF(iff&, IFFPARSE_SCAN&) = 0 THEN
-
- 'look for a VHDR stored property
- sp& = FindProp&(iff&, ID_8SVX&, ID_VHDR&)
- vhdr& = 0
- IF sp& THEN vhdr& = PEEKL(sp& + sp_Data)
- IF vhdr& THEN
- PRINT "VHDR info:"
- PRINT "oneShotHiSamples = ", PEEKL(vhdr&+vh_oneShotHiSamples)
- PRINT "repeatHiSamples = ", PEEKL(vhdr&+vh_repeatHiSamples)
- PRINT "samplesPerHiCycle = ", PEEKL(vhdr&+vh_samplesPerHiCycle)
- PRINT "samplesPerSec = ", PEEKW(vhdr&+vh_samplesPerSec)
- PRINT "Octaves = ", PEEKB(vhdr&+vh_Octaves)
- PRINT "Compression = ", PEEKB(vhdr&+vh_Compression)
- PRINT "volume = ", HEX$(PEEKL(vhdr&+vh_volume))
- IF PEEKB(vhdr&+vh_octaves)=1 AND _
- PEEKW(vhdr&+vh_samplesPerSec)<>0 AND _
- PEEKL(Vhdr&+vh_oneShotHiSamples)<>0 AND _
- PEEKL(Vhdr&+vh_repeatHiSamples)=0 THEN
- ' its a simple sampled sound rather than a musical instrument
- IF LoadSBody(iff&,vhdr&) THEN
- PRINT "loaded";sbytes&; "bytes of sample"
- PlaySample vhdr&
- END IF
- UnLoadSBody ' we must call this even if we failed to load
- ELSE
- PRINT "Its not a simple sound"
- END IF
- ELSE
- PRINT "No VHDR"
- END IF
- ELSE
- PRINT "Can't find VHDR and/or BODY"
- END IF
-
- CloseIFF iff&
- junk& = xClose(PEEKL(iff& + iff_Stream))
- FreeIFF iff&
- END IF
- ELSE
- PRINT filename$;" not found"
- END IF
- END IF
- END SUB
-
- '
- ' Start the main program
- '
- LIBRARY OPEN "dos.library"
- LIBRARY OPEN "graphics.library"
- LIBRARY OPEN "iffparse.library"
- LIBRARY OPEN "exec.library"
-
- OpenAudio
- IF devopened=0 THEN PRINT "Can't open audio":STOP
-
- IF LEN(COMMAND$) then
- ' we have a command line - play the file
- PlayFile COMMAND$
- ELSE
- ' No command line use the ASL file requester (only works on WB2 and up)
- LIBRARY OPEN "asl.library"
- DIM frtags&(20)
- TAGLIST VARPTR(frtags&(0)),ASLFR_TitleText&,"Sound Sample Info", _
- ASLFR_InitialFile&,"", _
- ASLFR_InitialDrawer&, CURDIR$, _
- TAG_DONE&
-
- fr&=AllocAslRequest&(ASL_FileRequest&,VARPTR(frtags&(0)))
- IF fr& THEN
- DO
- IF AslRequest&(fr&,0) THEN
- ' a file name was entered to the file requester, so build the filename
- ' from it and play the file
- filename$=PEEK$(PEEKL(fr&+fr_Drawer))
- IF RIGHT$(filename$,1)<>":" THEN
- filename$=filename$+"/"
- END IF
- filename$=filename$+PEEK$(PEEKL(fr&+fr_File))
- PlayFile filename$
- ELSE
- EXIT LOOP
- END IF
- LOOP
- FreeASlRequest fr&
- END IF
- END IF
- CloseAudio
-